"""
Ansible Management Models
"""
from django.db import models
from django.contrib.auth.models import User
from cmdb.models import Host


class AnsibleInventory(models.Model):
    """Ansible主机清单配置"""
    AUTH_TYPES = [
        ('password', '密码认证'),
        ('key', '密钥认证'),
    ]
    
    name = models.CharField(max_length=100, unique=True, verbose_name='配置名称')
    description = models.TextField(blank=True, verbose_name='描述')
    host_address = models.CharField(max_length=255, default='localhost', verbose_name='主机地址')
    ssh_port = models.IntegerField(default=22, verbose_name='SSH端口')
    ssh_user = models.CharField(max_length=100, default='root', verbose_name='SSH用户名')
    auth_type = models.CharField(max_length=20, choices=AUTH_TYPES, default='password', verbose_name='认证方式')
    ssh_password = models.CharField(max_length=200, blank=True, verbose_name='SSH密码')
    ssh_key = models.TextField(blank=True, verbose_name='SSH密钥')
    ansible_config_path = models.CharField(max_length=255, default='/etc/ansible/ansible.cfg', verbose_name='Ansible配置路径')
    inventory_path = models.CharField(max_length=255, default='/etc/ansible/hosts', verbose_name='Inventory路径')
    is_enabled = models.BooleanField(default=True, verbose_name='启用此配置')
    is_default = models.BooleanField(default=False, verbose_name='设为默认配置')
    hosts = models.ManyToManyField(Host, related_name='inventories', blank=True, verbose_name='主机列表')
    variables = models.JSONField(default=dict, blank=True, verbose_name='变量')
    created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name='inventories', verbose_name='创建者')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')

    class Meta:
        verbose_name = 'Ansible配置'
        verbose_name_plural = 'Ansible配置'
        ordering = ['-created_at']

    def __str__(self):
        return self.name
    
    def save(self, *args, **kwargs):
        # 如果设置为默认配置，取消其他配置的默认状态
        if self.is_default:
            AnsibleInventory.objects.filter(is_default=True).update(is_default=False)
        super().save(*args, **kwargs)


class AnsibleCredential(models.Model):
    """Ansible凭据"""
    CREDENTIAL_TYPES = [
        ('ssh_password', 'SSH密码'),
        ('ssh_key', 'SSH密钥'),
        ('vault', 'Ansible Vault'),
    ]

    name = models.CharField(max_length=100, unique=True, verbose_name='凭据名称')
    credential_type = models.CharField(max_length=20, choices=CREDENTIAL_TYPES, default='ssh_password', verbose_name='凭据类型')
    username = models.CharField(max_length=100, blank=True, verbose_name='用户名')
    password = models.CharField(max_length=200, blank=True, verbose_name='密码')
    ssh_key = models.TextField(blank=True, verbose_name='SSH私钥')
    become_method = models.CharField(max_length=20, default='sudo', verbose_name='提权方式')
    become_user = models.CharField(max_length=50, default='root', verbose_name='提权用户')
    become_password = models.CharField(max_length=200, blank=True, verbose_name='提权密码')
    description = models.TextField(blank=True, verbose_name='描述')
    created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name='credentials', verbose_name='创建者')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')

    class Meta:
        verbose_name = 'Ansible凭据'
        verbose_name_plural = 'Ansible凭据'
        ordering = ['-created_at']

    def __str__(self):
        return self.name


class AnsiblePlaybook(models.Model):
    """Ansible Playbook"""
    STATUS_CHOICES = [
        ('draft', '草稿'),
        ('active', '激活'),
        ('archived', '归档'),
    ]

    name = models.CharField(max_length=100, unique=True, verbose_name='Playbook名称')
    description = models.TextField(blank=True, verbose_name='描述')
    content = models.TextField(verbose_name='Playbook内容')
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='draft', verbose_name='状态')
    inventory = models.ForeignKey(AnsibleInventory, on_delete=models.SET_NULL, null=True, blank=True, 
                                  related_name='playbooks', verbose_name='默认清单')
    credential = models.ForeignKey(AnsibleCredential, on_delete=models.SET_NULL, null=True, blank=True,
                                   related_name='playbooks', verbose_name='默认凭据')
    variables = models.JSONField(default=dict, blank=True, verbose_name='变量')
    tags = models.CharField(max_length=200, blank=True, verbose_name='标签')
    created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name='playbooks', verbose_name='创建者')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')

    class Meta:
        verbose_name = 'Ansible Playbook'
        verbose_name_plural = 'Ansible Playbooks'
        ordering = ['-created_at']

    def __str__(self):
        return self.name


class AnsibleJob(models.Model):
    """Ansible执行任务"""
    STATUS_CHOICES = [
        ('pending', '等待中'),
        ('running', '运行中'),
        ('success', '成功'),
        ('failed', '失败'),
        ('canceled', '已取消'),
    ]

    JOB_TYPES = [
        ('playbook', 'Playbook'),
        ('adhoc', 'Ad-hoc'),
    ]

    job_type = models.CharField(max_length=20, choices=JOB_TYPES, verbose_name='任务类型')
    playbook = models.ForeignKey(AnsiblePlaybook, on_delete=models.SET_NULL, null=True, blank=True,
                                 related_name='jobs', verbose_name='Playbook')
    inventory = models.ForeignKey(AnsibleInventory, on_delete=models.SET_NULL, null=True,
                                  related_name='jobs', verbose_name='主机清单')
    credential = models.ForeignKey(AnsibleCredential, on_delete=models.SET_NULL, null=True,
                                   related_name='jobs', verbose_name='凭据')
    module = models.CharField(max_length=100, blank=True, verbose_name='模块名称')
    args = models.TextField(blank=True, verbose_name='模块参数')
    target_hosts = models.CharField(max_length=500, blank=True, verbose_name='目标主机')
    extra_vars = models.JSONField(default=dict, blank=True, verbose_name='额外变量')
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending', verbose_name='状态')
    result = models.TextField(blank=True, verbose_name='执行结果')
    stdout = models.TextField(blank=True, verbose_name='标准输出')
    stderr = models.TextField(blank=True, verbose_name='错误输出')
    duration = models.CharField(max_length=50, blank=True, verbose_name='执行耗时')
    start_time = models.DateTimeField(null=True, blank=True, verbose_name='开始时间')
    end_time = models.DateTimeField(null=True, blank=True, verbose_name='结束时间')
    created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name='ansible_jobs', verbose_name='创建者')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')

    class Meta:
        verbose_name = 'Ansible任务'
        verbose_name_plural = 'Ansible任务'
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.get_job_type_display()} - {self.id}"
